﻿using MelodysDemo.Application.Lists;
using MelodysDemo.Application.Questionnaires;
using Microsoft.EntityFrameworkCore;
using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Dynamic;

namespace MelodysDemo.API.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class QuestionnairesController : Controller
    {
        readonly IRepository<SurveyQuestionnaire, int> _Questnaire;//问卷
        readonly IRepository<SurveyQuestion, int> _Question;//问题
        readonly IRepository<SurveyOption, int> _Option;//选项
        readonly IQuestionnaireService _QuestionnaireService;
        public QuestionnairesController(IRepository<SurveyQuestionnaire, int> Questnaire,
                                        IQuestionnaireService questionnaireService,
                                        IRepository<SurveyQuestion, int> Question,
                                        IRepository<SurveyOption, int> Option)
        {
            _Questnaire = Questnaire;
            _QuestionnaireService = questionnaireService;
            _Question = Question;
            _Option = Option;
        }
        //查询
        [HttpPost]
        public async Task<IActionResult> Questionnaires([FromBody] QuestionnaireInput input)
        {
            var list = await _QuestionnaireService.GetResultDto(input);
            return Json(new VueResult<SurveyQuestionnaire> { code = 0, msg = "请求成功", count = list.TotalCount, data = list.Data });
        }

        //导入问卷
        [HttpPost]
        /*[AllowAnonymous]*/
        public async Task<IActionResult> ImportQuestionnaire(IFormFile file)
        {
            try
            {
                if (file == null)
                    return Json(new UIResult(-1, "请选择要上传的文件"));
                var postFile = Request.Form.Files[0];//接收前端传输的文件
                string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
                string extName = Path.GetExtension(postFile.FileName);//获取后缀名
                string excName = Path.GetFileNameWithoutExtension(postFile.FileName);//获取问卷名
                //判断是否为Excel文件
                if (!new string[] { ".xls", ".xlsx" }.Contains(extName))
                {
                    return Json(new UIResult(-1, "必须是Excel文件"));
                }
                //创建一个内存流，用于将上传的文件内容保存在内存中
                MemoryStream ms = new MemoryStream();
                //将上传的文件内容复制到内存流中
                postFile.CopyTo(ms);
                //将内存流的位置设置为开始，以便后续读取文件内容
                ms.Position = 0;
                //用于存储 Excel 工作簿对象
                IWorkbook wb = null;
                if (extName.ToLower().Equals(".xls"))//97-2003版本
                {
                    //创建一个 HSSFWorkbook 对象，表示 Excel 97-2003 版本的工作簿，并将内存流中的内容加载到工作簿中。
                    wb = new HSSFWorkbook(ms);
                }
                else
                {
                    //创建一个 XSSFWorkbook 对象，表示 Excel 2007 及以上版本的工作簿，并加载内存流中的内容。
                    wb = new XSSFWorkbook(ms);//2007以上版本
                }
                //获取工作簿中的第一个工作表（sheet）并将其保存在 sheet 变量中
                ISheet sheet = wb.GetSheetAt(0);

                //总行数(0开始)
                int totalRow = sheet.LastRowNum;
                //总列数(1开始)
                int totalColumn = sheet.GetRow(0).LastCellNum;

                //获取每个问题的最高分数
                int Sscore = totalColumn - 3;

                //填充 SurveyQuestionnaire 表
                SurveyQuestionnaire? sqn = new SurveyQuestionnaire
                {
                    Title = excName,//问卷名
                    QuestionCount = (byte)totalRow,//问题数
                    TotalScore = (short)(totalRow * Sscore),//总分
                    Status = 0,//状态
                    Version = 0,//版本号
                    CreateTime = DateTime.Now,//创建时间
                    Creator = uname,//创建人
                    ModifiedTime = DateTime.Now,//修改时间
                    Modifier = uname,//修改人
                    IsDelete = 0//删除标识
                };
                SurveyQuestionnaire? r= await _Questnaire.InsertAsync(sqn);
                //根据 Excel 数据逐步创建实体对象
                for (int i = 1; i <= totalRow; i++)
                {
                    IRow row = sheet.GetRow(i);//获取当前行的列数
                    string? title = row.GetCell(1).ToString();//获取题干
                    //填充 SurveyQuestion 表
                    SurveyQuestion? sq = new SurveyQuestion
                    {
                        Title = title,//问题
                        QuestionnaireId = sqn.Id,//问卷ID
                        Sn = (byte)(i),//序号
                        Score = (byte)Sscore,//分值
                        Version = 0,//版本号
                        CreateTime = DateTime.Now,//创建时间
                        Creator = uname,//创建人
                        ModifiedTime = DateTime.Now,//修改时间
                        Modifier = uname,//修改人
                        IsDelete = 0//删除标识
                    };
                    await _Question.InsertAsync(sq);
                    //填充 SurveyOption 表
                    byte score = (byte)Sscore;
                    for (int j = 2; j < row.Count() - 1; j++)
                    {
                        string? content = row.GetCell(j).ToString();
                        SurveyOption? so = new SurveyOption
                        {
                            QuestionId = sq.Id,//问题ID
                            QuestionnaireId = 0,//问卷ID
                            Content = content,//选项
                            Sn = (byte)(j - 1),
                            Score = score,//分数
                            Version = 0,//版本号
                            CreateTime = DateTime.Now,//创建时间
                            Creator = uname,//创建人
                            ModifiedTime = DateTime.Now,//修改时间
                            Modifier = uname,//修改人
                            IsDelete = 0//删除标识
                        };
                        score--;
                        SurveyOption? sos = await _Option.InsertAsync(so);
                    }
                }
                if(r!=null)
                    return Json(new UIResult(0, "导入成功"));
                return Json(new UIResult(-1, "数据异常"));

            }
            catch (Exception e)
            {

                return Json(new UIResult(-1, $"错误：{e.Message}"));
            }
        }

        //下载模板
        [HttpGet]
        [AllowAnonymous]
        public IActionResult DownloadTemplate()
        {
            // 问卷模板文件的路径，根据实际存放位置进行修改
            string templateFilePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Template.xlsx");

            // 读取问卷模板文件的内容
            var fileBytes = System.IO.File.ReadAllBytes(templateFilePath);

            // 返回问卷模板文件给前端进行下载
            return File(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "调查问卷模板.xlsx");
        }

        //修改状态
        //1:启用
        [HttpPatch]
        public async Task<IActionResult> QuestnaireStatusNo([FromBody] List<int> ids)
        {
            string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
            foreach (int id in ids)
            {
                var qn = await _Questnaire.FirstOrDefaultAsync(x => x.Id == id);
                if (qn != null)
                {
                    qn.Status = 1;//启用
                    qn.Modifier = uname;
                    qn.ModifiedTime = DateTime.Now;
                    qn.Version++;
                    await _Questnaire.UpdateAsync(qn);
                }
            }
            return Json(new UIResult(0, "已全部启用"));
        }
        //2:禁用
        [HttpPatch]
        public async Task<IActionResult> QuestnaireStatusOff([FromBody] List<int> ids)
        {
            string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
            foreach (int id in ids)
            {
                var qn = await _Questnaire.FirstOrDefaultAsync(x => x.Id == id);
                if (qn != null)
                {
                    qn.Status = 2;//禁用
                    qn.Modifier = uname;
                    qn.ModifiedTime = DateTime.Now;
                    qn.Version++;
                    await _Questnaire.UpdateAsync(qn);
                }
            }
            return Json(new UIResult(0, "已全部禁用"));
        }

        //下载问卷
        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> QuestionnaireDownload([FromQuery] int id)
        {
            //获取问卷
            var qn = _Questnaire
                                    .FirstOrDefault(x => x.Id == id);
            //获取问卷的所有问题
            var qs = _Question.GetAll()
                                        .Include(q => q.SurveyOptions)
                                        .Where(q => q.QuestionnaireId == qn.Id).ToList();
            //动态生成列名
            var columnNames = new List<string> { "序号", "题干" };
            string[] OptionsColumn = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
            foreach (SurveyQuestion q in qs)
            {
                for (int i = 1; i <= q.SurveyOptions.Count; i++)
                {
                    //columnNames.Add(((char)('A' + i - 1)).ToString());
                    columnNames.Add(OptionsColumn[i - 1].ToString());
                    //columnNames.Add("选项" + i);
                }
                break;
            }
            columnNames.Add("得分");
            //创建动态类型的属性
            var properties = new List<PropertyDescriptor>();
            foreach (string columnName in columnNames)
            {
                properties.Add(new DynamicPropertyDescriptor(columnName, item =>
                {
                    var dict = (IDictionary<string, object>)item;
                    return dict[columnName];
                }));
            }
            //创建动态类型列表
            var dynamicList = new List<ExpandoObject>();
            int sequence = 1;
            foreach (SurveyQuestion q in qs)
            {
                dynamic item = new ExpandoObject();
                int oCount = 0;//初始选项数
                var dict = (IDictionary<string, object>)item;
                dict["序号"] = sequence;
                dict["题干"] = q.Title;
                for (int i = 1; i <= q.SurveyOptions.Count; i++)
                {
                    //dict[((char)('A' + i - 1)).ToString()] = q.SurveyOptions.FirstOrDefault(o => o.Sn == i).Content;
                    dict[OptionsColumn[i - 1].ToString()] = q.SurveyOptions.FirstOrDefault(o => o.Sn == i).Content;
                    oCount++;
                }
                //根据选项数量生成对应的得分，并使用 Reverse 将序列逆转
                string str = string.Join(",", Enumerable.Range(1, oCount).Reverse());
                dict["得分"] = str;
                dynamicList.Add(item);
                sequence++;
            }
            /* var str = "5,4,3,2,1";
             //将问题和选项存放到自定义的Excel类
             var list = await q.Select(x => new QuestionDto
             {
                 序号 = x.Sn,
                 题干 = x.Title,
                 A = x.SurveyOptions.FirstOrDefault(o => o.Sn == 1).Content,
                 B = x.SurveyOptions.FirstOrDefault(o => o.Sn == 2).Content,
                 C = x.SurveyOptions.FirstOrDefault(o => o.Sn == 3).Content,
                 D = x.SurveyOptions.FirstOrDefault(o => o.Sn == 4).Content,
                 E = x.SurveyOptions.FirstOrDefault(o => o.Sn == 5).Content,
                 得分 = str
             }).ToListAsync();*/
            //将List转换为DataTable
            //DataTable dt = ToExcel.ToDataTable<QuestionDto>(list);
            DataTable dt = ToExcel.ToDataTableFromExpandoObjects(properties, dynamicList);
            //dt转换为二进制文件
            byte[] file = ToExcel.DataTableToExcel(dt, qn.Title, true);
            //导出
            return File(file, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        }

        //删除
        [HttpGet]
        public async Task<IActionResult> QuestnaireDel([FromQuery] int id)
        {
            var obj = await _Questnaire.FirstOrDefaultAsync(u => u.Id == id);
            string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
            obj.IsDelete = 1;//修改删除状态
            obj.Modifier = uname;
            obj.ModifiedTime = DateTime.Now;
            obj.Version++;
            SurveyQuestionnaire? r = await _Questnaire.UpdateAsync(obj);
            if (r != null)
            {

                return Json(new UIResult(0, "删除成功"));
            }
            return Json(new UIResult(-1, "删除失败"));
        }

    }
}
